package com.spzx.channel.service.impl;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.spzx.channel.domain.vo.ItemVo;
import com.spzx.channel.service.ItemService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.common.core.utils.JwtUtils;
import com.spzx.common.core.utils.StringUtils;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.product.api.domain.Product;
import com.spzx.product.api.domain.ProductDetails;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPriceVo;
import com.spzx.product.api.domain.vo.SkuStockVo;
import com.spzx.product.api.service.RemoteProductService;
import com.spzx.user.api.domain.UserBrowseHistory;
import com.spzx.user.api.service.RemoteUserBrowseHistoryService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

@Service
@Slf4j
public class ItemServiceImpl implements ItemService {

    @Autowired
    private RemoteProductService remoteProductService;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private RemoteUserBrowseHistoryService remoteUserBrowseHistoryService;

    @Override
    public ItemVo item(Long skuId) {
        ItemVo itemVo = new ItemVo();

        //0、布隆过滤器
        RBloomFilter<Object> bloomFilter = redissonClient.getBloomFilter("sku:bloom:filter");
        if (!bloomFilter.contains(skuId)) {
            log.error("商品信息不存在 skuId：{}", skuId);
            throw new ServiceException("商品信息不存在");
        }

        //有返回值的异步方法
        CompletableFuture<ProductSku> futureProductSku = CompletableFuture.supplyAsync(() -> {
            //1、获取商品sku信息
            R<ProductSku> productSkuResult = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSkuResult.getCode()) {
                log.error(productSkuResult.getMsg());
                throw new ServiceException(productSkuResult.getMsg());
            }
            //获取sku实体的信息
            ProductSku productSku = productSkuResult.getData();
            itemVo.setProductSku(productSku);

            return productSku;
        }, threadPoolExecutor);

        //异步执行，并且获取商品sku方法的返回值，本身没有返回值
        CompletableFuture<Void> futureProduct = futureProductSku.thenAcceptAsync(productSku -> {

            //2、获取商品信息
            Long productId = productSku.getProductId();
            R<Product> productResult = remoteProductService.getProduct(productId, SecurityConstants.INNER);
            if (R.FAIL == productResult.getCode()) {
                log.error(productResult.getMsg());
                throw new ServiceException(productResult.getMsg());
            }
            //获取sku所属的商品信息
            Product product = productResult.getData();
            itemVo.setProduct(product);

            //7、商品轮播图
            String sliderUrls = product.getSliderUrls();

            //8、商品规格信息
            String specValue = product.getSpecValue();
            JSONArray specValueList = JSON.parseArray(specValue);

            itemVo.setSpecValueList(specValueList);
            itemVo.setSliderUrlList(Arrays.asList(sliderUrls.split(",")));
        });

        //异步执行，不需要获取上一个方法的返回值，本身也没有返回值
        CompletableFuture<Void> futureSkuPrice = CompletableFuture.runAsync(() -> {
            //3、获取商品价格信息
            R<SkuPriceVo> skuPriceResult = remoteProductService.getSkuPrice(skuId, SecurityConstants.INNER);
            if (R.FAIL == skuPriceResult.getCode()) {
                log.error(skuPriceResult.getMsg());
                throw new ServiceException(skuPriceResult.getMsg());
            }
            SkuPriceVo skuPriceVo = skuPriceResult.getData();

            itemVo.setSkuPrice(skuPriceVo);
        }, threadPoolExecutor);


        //异步执行，并且获取商品sku方法的返回值，本身没有返回值
        CompletableFuture<Void> futureProductDetails = futureProductSku.thenAcceptAsync(productSku -> {
            //4、获取商品详情图片信息
            R<ProductDetails> productDetailsResult = remoteProductService.getProductDetails(productSku.getProductId(), SecurityConstants.INNER);
            if (R.FAIL == productDetailsResult.getCode()) {
                log.error(productDetailsResult.getMsg());
                throw new ServiceException(productDetailsResult.getMsg());
            }
            ProductDetails productDetails = productDetailsResult.getData();
            List<String> imagesUrlList = Arrays.asList(productDetails.getImageUrls().split(","));
            itemVo.setDetailsImageUrlList(imagesUrlList);
        });


        //异步执行，并且获取商品sku方法的返回值，本身没有返回值
        CompletableFuture<Void> futureSkuSpecValue = futureProductSku.thenAcceptAsync(productSku -> {
            //5、获取商品所有SKU规格详细map信息
            R<Map<String, Long>> skuSpecValueResult = remoteProductService.getSkuSpecValue(productSku.getProductId(), SecurityConstants.INNER);
            if (R.FAIL == skuSpecValueResult.getCode()) {
                log.error(skuSpecValueResult.getMsg());
                throw new ServiceException(skuSpecValueResult.getMsg());
            }
            Map<String, Long> skuSpecValueMap = skuSpecValueResult.getData();
            itemVo.setSkuSpecValueMap(skuSpecValueMap);
        });

        //异步执行，不需要获取上一个方法的返回值，本身也没有返回值
        CompletableFuture<Void> futureSkuStock = CompletableFuture.runAsync(() -> {
            //6、获取商品sku库存信息
            R<SkuStockVo> skuStockResult = remoteProductService.getSkuStock(skuId, SecurityConstants.INNER);
            if (R.FAIL == skuStockResult.getCode()) {
                log.error(skuStockResult.getMsg());
                throw new ServiceException(skuStockResult.getMsg());
            }
            SkuStockVo skuStockVo = skuStockResult.getData();
            itemVo.setSkuStockVo(skuStockVo);
        }, threadPoolExecutor);

        //等待所有任务都完成
        CompletableFuture.allOf(
                        futureProductSku,
                        futureProduct,
                        futureProductDetails,
                        futureSkuPrice,
                        futureSkuSpecValue,
                        futureSkuStock)
                .join();//这是一个阻塞操作，程序会在此等待直到所有任务都完成。

        //获取登录的用户id
        String token = SecurityUtils.getToken();
        //获取用户id
        String userId = JwtUtils.getUserId(token);
        if(StringUtils.hasText(userId)){
            //创建UserBrowseHistory对象
            UserBrowseHistory userBrowseHistory = new UserBrowseHistory();
            //设置用户id
            userBrowseHistory.setUserId(Long.parseLong(userId));
            //设置商品skuId
            userBrowseHistory.setSkuId(skuId);
            //远程调用用户微服务保存浏览记录
            remoteUserBrowseHistoryService.saveUserBrowseHistory(userBrowseHistory,SecurityConstants.INNER);
        }

        //返回商品详情
        return itemVo;
    }
}
